<!-- 后写的页面
 bug：
 1.文字流失输出首个出现换行符
  -->

<template>
  <div style="height: calc(100vh - 100px)">
    <div class="talkContainer">
      <div class="talkContent" ref="chatContent">
        <div class="all">
          <div class="icon">
            <img src="@/assets/images/talk.png" alt="" />
          </div>
          <div class="aitalk" v-html="aitalk" v-cloak></div>
        </div>
        <div class="talkQA" v-for="(item, index) in talkList" :key="item.id">
          <div v-if="item.person == 'mine'" class="mine">
            <img
              style="width: 100px; height: 100px"
              v-if="item.img"
              :src="item.img"
              alt=""
            />
            <div class="question">
              {{ item.say }}
            </div>
            <div class="icon">
              <img src="@/assets/images/mine.png" alt="" />
            </div>
          </div>
          <div
            v-if="item.person == 'ai'"
            class="all"
            style="margin-bottom: 10px"
          >
            <div class="icon">
              <img src="@/assets/images/talk.png" alt="" />
            </div>
            <div class="aitalk" v-html="item.say"></div>
          </div>
          <div v-if="item.person == 'ai' && !isDisabled" class="assess">
            <!-- <el-popover
              :ref="`popover-${index}`"
              placement="top"
              width="200"
              trigger="click"
            >
              <el-checkbox-group v-model="checkboxGroup1">
                <el-checkbox
                  v-for="option in options"
                  :label="option"
                  :key="option"
                  border
                  >{{ option }}</el-checkbox
                >
              </el-checkbox-group>
              <el-input
                v-model="other"
                type="textarea"
                :autosize="{ minRows: 2, maxRows: 4 }"
                placeholder="其他"
              ></el-input>
              <div style="text-align: right; margin: 20px 0">
                <el-button @click="visible = false">取消</el-button>
                <el-button type="primary" @click="ok(item)">确认</el-button>
              </div>
              <img
                slot="reference"
                :src="
                  item.isBad
                    ? require('@/assets/images/bad-a.png')
                    : require('@/assets/images/bad.png')
                "
                alt=""
                @click="getBad(item, index)"
              />
            </el-popover>
            <img
              :src="
                item.isGood
                  ? require('@/assets/images/good-a.png')
                  : require('@/assets/images/good.png')
              "
              alt=""
              @click="getGood(item, index)"
            /> -->

            <el-popover
              placement="bottom"
              title="期待您的反馈"
              width="400"
              trigger="click"
              v-model="visible"
              @hide="hideDiv(item, index)"
            >
              <el-checkbox-group v-model="checkboxGroup1">
                <el-checkbox
                  v-for="option in options"
                  :label="option"
                  :key="option"
                  border
                  >{{ option }}</el-checkbox
                >
              </el-checkbox-group>
              <el-input
                v-model="other"
                type="textarea"
                :autosize="{ minRows: 2, maxRows: 4 }"
                placeholder="其他"
              ></el-input>
              <div style="text-align: right; margin: 20px 0">
                <el-button @click="visible = false">取消</el-button>
                <el-button type="primary" @click="ok(item)">确认</el-button>
              </div>
              <img
                slot="reference"
                :src="
                  item.isBad
                    ? require('@/assets/images/bad-a.png')
                    : require('@/assets/images/bad.png')
                "
                alt=""
                @click="getBad(item, index)"
              />
            </el-popover>
            <img
              :src="
                item.isGood
                  ? require('@/assets/images/good-a.png')
                  : require('@/assets/images/good.png')
              "
              alt=""
              @click="getGood(item, index)"
            />
          </div>
        </div>
      </div>
      <div class="talkInput">
        <div class="select">
          <span>信号专业知识库</span>
        </div>
        <form @submit.prevent="getQuestion" class="userSearch">
          <div class="content">
            <div class="upload">
              <el-upload
                action="#"
                :limit="1"
                :file-list="fileList"
                :on-change="handleChange"
                :auto-upload="false"
                list-type="picture"
                accept=".jpg,.png"
                @keydown.enter.native="getQuestion"
              >
                <el-button size="small" style="padding: 0">
                  <i
                    class="el-icon-picture"
                    style="font-size: 30px; color: #28c76c"
                  ></i>
                </el-button>
              </el-upload>
            </div>
            <div class="input">
              <el-input
                v-model="contentVal"
                type="textarea"
                placeholder="请输入内容"
                style="resize: none"
                autosize
                :row="1"
                :maxlength="200"
                @keydown.enter.native="getQuestion"
                :disabled="isDisabled"
              ></el-input>
            </div>
          </div>
        </form>
        <div class="send">
          <i
            class="el-icon-s-promotion"
            style="font-size: 30px; color: #28c76c; margin-right: 20px"
            @click="getQuestion"
          ></i>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { marked } from "marked";

export default {
  data() {
    return {
      aitalk: "",
      talkList: [],
      contentVal: "",
      fileList: [],
      file: "",
      isDisabled: false,
      imgUrl: "",
      kb_name: "1be049f5183647b081c7ea6dd21948b2",
      bad: false,
      good: false,
      user_id: JSON.parse(localStorage.getItem("userInfo")).id,
      options: [
        "答非所问",
        "回答有误",
        "格式问题",
        "没有帮助",
        "事实错误",
        "有害信息",
      ],
      checkboxGroup1: [],
      visible: false,
      other: "",
      desc: "",
    };
  },
  created() {
    this.getShow();
  },
  updated() {
    this.scrollToBottom();
  },

  methods: {
    scrollToBottom() {
      this.$nextTick(() => {
        this.$refs.chatContent.scrollTop = this.$refs.chatContent.scrollHeight;
      });
    },
    handleChange(file, fileList) {
      this.file = file.raw;
      this.fileList = fileList;
      this.imgUrl = file.url;
    },
    async getShow() {
      let text = `
        <h1>🚄 你好，我是你的信号专业多模态大模型助手—POC测试</h1>
        <p>👋 我由商汤科技打造，接入了最新的知识库及多模态大模型，能够为你提供专业的工程领域知识参考，是你的工作好帮手～</p>
        <p>你可以在提问框旁选择对应的知识库，让我帮你准确地查询有关的专业知识。</p>
        <p>我有以下一些功能：</p>
        <p>🔍 基于特定的专业知识库，帮你检索对应的法规规范</p>
        <p>👀 上传专业图片，帮你解释图片内容</p>
        <p>❎ 在POC测试阶段，如果你问的问题和专业无关，我会拒绝你哦！</p>
        <br>
        <p>你可以尝试这样来问我：</p>
        <p>- 临时限速服务器（TSRS）与下列哪些系统接口？</p>
        <p>- 调度集中系统(CTC)具备哪两种作业办理模式？</p>
        <p>- 自动闭塞区间信号设备管辖分界要满足哪些要求？</p>
        
        `;
      let m = "";

      for (let i = 0; i < text.length; i++) {
        m += text.charAt(i);
        await new Promise((resolve) => {
          setTimeout(resolve, 30);
        });
        this.aitalk = m;
      }
    },
    getQuestion(event) {
      event.preventDefault();
      if (this.fileList && this.fileList.length > 0) {
        if (this.contentVal) {
          this.talkList.push(
            {
              id: this.generateUniqueID(),
              person: "mine",
              img: this.imgUrl,
            },
            {
              id: this.generateUniqueID(),
              person: "mine",
              say: this.contentVal,
            },
            {
              id: this.generateUniqueID(),
              person: "ai",
              isGood: false,
              isBad: false,
              say: "让我想一想",
            }
          );
        } else {
          this.talkList.push(
            {
              id: this.generateUniqueID(),
              person: "mine",
              img: this.imgUrl,
            },
            {
              id: this.generateUniqueID(),
              person: "ai",
              say: "让我想一想",
            }
          );
        }
        this.isDisabled = true;
        this.getAnswer1();
        this.contentVal = "";
        this.fileList = [];
      } else {
        if (this.contentVal == "") {
          this.$message.warning("请输入提问内容");
        }
        this.talkList.push(
          {
            id: this.generateUniqueID(),
            person: "mine",
            say: this.contentVal,
          },
          {
            id: this.generateUniqueID(),
            person: "ai",
            isGood: false,
            isBad: false,
            say: "让我想一想",
          }
        );
        this.isDisabled = true;
        this.getAnswer();
        this.contentVal = "";
      }
    },

    async getAnswer() {
      let last = this.talkList[this.talkList.length - 1];
      last.question = this.contentVal;
      let isSend = true;
      let timer = setInterval(() => {
        if (isSend) {
          if (last.say.length >= 5) {
            last.say += "· ";
          }
          if (last.say.length > 11) {
            last.say = "让我想一想";
          }
        }
      }, 200);
      let res = await fetch(
        "http://103.237.29.235:7866/chat/knowledge_base_chat",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            query: this.contentVal,
            session_id: "session_id",
            kb_name: this.kb_name,
            stream: true,
          }),
        }
      );
      if (res) {
        const reader = res.body.getReader();
        const textDecoder = new TextDecoder();
        let index = 1;
        while (true) {
          const { done, value } = await reader.read();
          if (index == 1) {
            last.say = "";
            clearInterval(timer);
          }

          if (done) {
            this.isDisabled = false;
            this.good = false;
            this.bad = false;
            break;
          } else {
            const text = textDecoder.decode(value);
            index++;
            for (let i = 0; i < text.length; i++) {
              last.say += text.charAt(i);
              await new Promise((resolve) => {
                setTimeout(resolve, 10);
              });
            }
          }
        }
        // last.say = marked(last.say);
      } else {
        return false;
      }
    },
    //多模态
    async getAnswer1() {
      let last = this.talkList[this.talkList.length - 1];
      let isSend = true;
      let timer = setInterval(() => {
        if (isSend) {
          if (last.say.length >= 5) {
            last.say += "· ";
          }
          if (last.say.length > 11) {
            last.say = "让我想一想";
          }
        }
      }, 200);
      const formData = new FormData();
      formData.append("file", this.file);
      formData.append("query", this.contentVal);
      formData.append("kb_name", this.kb_name);
      formData.append("stream", true);
      let res = await fetch("http://103.237.29.235:7866/chat/multimodal_chat", {
        method: "POST",
        body: formData,
      });
      if (res) {
        const reader = res.body.getReader();
        const textDecoder = new TextDecoder();
        let index = 1;
        while (true) {
          const { done, value } = await reader.read();
          if (index == 1) {
            last.say = "";
            clearInterval(timer);
          }

          if (done) {
            this.isDisabled = false;
            this.good = false;
            this.bad = false;
            break;
          } else {
            const text = textDecoder.decode(value);
            index++;
            for (let i = 0; i < text.length; i++) {
              last.say += text.charAt(i);
              await new Promise((resolve) => {
                setTimeout(resolve, 10);
              });
            }
          }
        }
        last.say = marked.parse(last.say);
      } else {
        return false;
      }
    },
    //生成id

    generateUniqueID() {
      // 使用当前日期和时间以及随机数生成唯一ID
      const time = new Date().getTime();
      const random = Math.random().toString(36).substring(2, 15);
      return "id_" + time + "_" + random;
    },
    getBad(row, index) {
      console.log(this.talkList[index]);

      // this.bad = !this.bad;
      // this.checkboxGroup1 = [];
      // this.other = "";
      // this.desc = "";

      // if (this.bad && this.talkList[index].isBad == false) {
      //   this.good = false;
      //   this.talkList[index].isGood = false;
      //   this.visible = false;
      // } else {
      //   this.visible = true;

      //   this.$http
      //     .post("http://103.237.29.235:7866/feedback/cancel_vote", {
      //       user_id: this.user_id,
      //       feedback_id: this.talkList[index].feedback_id,
      //     })
      //     .then((res) => {
      //       let result = res.data;
      //       this.talkList[index].isBad = false;
      //       if (result.code == 200) {
      //         this.$message.success("操作完成");
      //       }
      //     });
      // }
    },
    getGood(row) {
      this.good = !this.good;

      if (this.good) {
        this.bad = false;
        row.isBad = false;
      }
      let data = {
        user_id: this.user_id,
        query: row.question,
        answer: row.say,
        kb_name: this.kb_name,
        status: "upvote",
        desc: this.desc,
      };
      if (this.good) {
        this.$http
          .post("http://103.237.29.235:7866/feedback/vote", data)
          .then((res) => {
            let result = res.data;
            if (result.code == 200) {
              row.feedback_id = result.data.feedback_id;
              row.isGood = true;
              this.$message.success("操作完成");
            }
          });
      } else {
        this.$http
          .post("http://103.237.29.235:7866/feedback/cancel_vote", {
            user_id: this.user_id,
            feedback_id: row.feedback_id,
          })
          .then((res) => {
            let result = res.data;
            if (result.code == 200) {
              row.isGood = false;
              this.$message.success("操作完成");
            }
          });
      }
    },
    ok(row) {
      this.visible = false;
      if (this.other) {
        this.checkboxGroup1.push(this.other);
      }
      this.desc = this.checkboxGroup1.join(",");

      if (this.desc && this.bad) {
        this.pick(row);
      }
    },
    hideDiv(row, index) {
      console.log(index);

      if (this.desc == "" && this.bad) {
        // this.pick(row, index);
      }
    },

    pick(row, index) {
      console.log(this.talkList[index]);

      // let data = {
      //   user_id: this.user_id,
      //   query: this.talkList[index].question,
      //   answer: this.talkList[index].say,
      //   kb_name: this.kb_name,
      //   status: "downvote",
      //   desc: this.desc,
      // };
      // this.$http
      //   .post("http://103.237.29.235:7866/feedback/vote", data)
      //   .then((res) => {
      //     let result = res.data;

      //     if (result.code == 200) {
      //       this.talkList[index].feedback_id = result.data.feedback_id;

      //       this.talkList[index].isBad = true;
      //       this.$message.success("感谢您的反馈");
      //     }
      //   });
    },
  },
};
</script>

<style  scoped>
.talkContainer {
  width: 80%;
  margin: 10px auto;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.talkContent {
  width: 100%;
  flex: 1;
  overflow: auto;
}

.talkContent::-webkit-scrollbar {
  display: none;
}
.talkInput {
  width: 100%;
  margin: 30px 0;
  background-color: #fff;
  border-radius: 15px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  padding: 10px;
}

.img-list {
  display: flex;
  align-items: center;
  justify-content: start;
}

.all {
  display: flex;
  justify-content: start;
  align-items: center;
}

.icon img {
  width: 20px;
  height: 20px;
}

.aitalk {
  margin-left: 10px;
  padding: 8px 10px 12px;
  background-color: #fff;
  border-radius: 15px;
}
.userSearch {
  display: flex;
  flex: 1;
}
.content {
  width: 100%;
  display: flex;
  justify-content: start;
  align-items: center;
}

.el-textarea /deep/ .el-textarea__inner {
  resize: none;
  border: none;
}
.input {
  flex: 1;
  display: flex;
  align-items: center;
}
.el-textarea {
  display: flex;
  align-items: center;
  font-size: 20px !important;
  font-weight: 600;
}
.select,
.send,
.upload {
  margin: 0 10px;
}

.mine {
  display: flex;
  justify-content: end;
  align-items: center;
  padding: 15px 0;
  margin: 20px 0;
}
.ai {
  display: flex;
  justify-content: start;
  align-items: center;
  background-color: #fff;
  padding: 15px 0;
}

.question {
  margin-right: 10px;
  font-weight: 600;
}
.upload div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 10px;
}
.upload /deep/ .el-upload-list__item-name {
  display: none;
}
.upload /deep/.el-upload-list__item-thumbnail {
  width: 50px;
  height: 50px;
  position: absolute;
  margin-left: 0px;
}
.upload /deep/ .el-upload-list__item {
  width: 80px;
  height: 80px;
  padding: 15px 0 0 13px;
}

.upload /deep/ .el-icon-close {
  right: 0;
}

.assess {
  margin-left: 20px;
}
.assess img {
  width: 20px;
  height: 20px;
  margin: 1px 10px;
}
.el-popover .el-button {
  border: 1px solid #dcdfe6;
}
.el-popover .el-textarea {
  border: 1px solid #dcdfe6;
  margin: 10px;
  width: 360px;
}
.el-checkbox /deep/ .el-checkbox__input {
  display: none;
}
.el-checkbox {
  margin: 10px;
}
</style>